package pl.edu.agh.ki.ewywiadowka.client.windows.educator;

import java.util.LinkedList;

import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.gen2.table.client.FixedWidthFlexTable;
import com.google.gwt.gen2.table.client.FixedWidthGrid;
import com.google.gwt.gen2.table.client.ScrollTable;
import com.google.gwt.gen2.table.client.AbstractScrollTable.SortPolicy;
import com.google.gwt.gen2.table.override.client.HTMLTable.RowFormatter;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.DockPanel;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.ScrollPanel;
import com.google.gwt.user.client.ui.SourcesTableEvents;
import com.google.gwt.user.client.ui.TableListener;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.datepicker.client.DateBox;

import pl.edu.agh.ki.ewywiadowka.client.Const;
import pl.edu.agh.ki.ewywiadowka.client.EWywiadowka;
import pl.edu.agh.ki.ewywiadowka.client.Const.Error.AbsenceRegisterMsg;
import pl.edu.agh.ki.ewywiadowka.client.dto.AbsenceDTO;
import pl.edu.agh.ki.ewywiadowka.client.dto.StudentDTO;
import pl.edu.agh.ki.ewywiadowka.client.windows.GenericWindow;

public class AbsenceWindow extends GenericWindow implements TableListener,
		ClickHandler {

	private ScrollPanel _mainPanel = new ScrollPanel();
	private DockPanel _dockPanel = new DockPanel();
	private ScrollTable _scrollTable = null;
	private Button _addButton = new Button("Dodaj nieobecnosc");
	private Button _removeButton = new Button("Usun nieobecnosc");
	private Button _excuseButton = new Button("Usprawiedliw nieobecnosc");

	private VerticalPanel _buttonsPanel = new VerticalPanel();
	private HorizontalPanel _addAbsencePanel = new HorizontalPanel();
	private HorizontalPanel _restButtonPanel = new HorizontalPanel();
	private Grid _addAbsenceGrid = new Grid(2, 3);
	private DateBox _startDateBox = new DateBox();
	private DateBox _stopDateBox = new DateBox();
	private CheckBox _excusedCheckBox = new CheckBox();

	private FixedWidthGrid _dataTable;
	private FixedWidthFlexTable _headerTable;

	private int _selectedRow = -1;

	private AbsenceWindow _me;

	private LinkedList<AbsenceDTO> _absences = null; // bo na poczatku nie ma

	private int _mode = -1;

	private StudentDTO _student;

	public AbsenceWindow(EWywiadowka wywiadowka, StudentDTO student, int mode) {

		super(wywiadowka);

		_mode = mode;
		_me = this;
		_student = student;

		_dataTable = new FixedWidthGrid(0, 3);
		_dataTable.setBorderWidth(1);

		_headerTable = new FixedWidthFlexTable();
		_headerTable.setBorderWidth(1);
		fillHeader();

		_scrollTable = new ScrollTable(_dataTable, _headerTable);
		_scrollTable.fillWidth();
		_scrollTable.setHeight("400px");

		_addButton.addClickHandler(this);
		_removeButton.addClickHandler(this);
		_excuseButton.addClickHandler(this);

		_restButtonPanel.add(_removeButton);
		_restButtonPanel.add(_excuseButton);

		_addAbsenceGrid.setWidget(0, 0, new Label("Poczatek"));
		_addAbsenceGrid.setWidget(0, 1, new Label("Koniec"));
		_addAbsenceGrid.setWidget(0, 2, new Label("Usprawiedliwienie"));
		_addAbsenceGrid.setWidget(1, 0, _startDateBox);
		_addAbsenceGrid.setWidget(1, 1, _stopDateBox);
		_addAbsenceGrid.setWidget(1, 2, _excusedCheckBox);

		_addAbsencePanel.add(_addAbsenceGrid);
		_addAbsencePanel.add(_addButton);

		_buttonsPanel.add(_restButtonPanel);
		_buttonsPanel.add(_addAbsencePanel);

		_dockPanel.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER);
		_dockPanel.add(new Label("Uczen: " + student.toString()),
				DockPanel.NORTH);
		_dockPanel.add(_scrollTable, DockPanel.CENTER);
		if (_mode == 1)
			_dockPanel.add(_buttonsPanel, DockPanel.SOUTH);
		else
			_dockPanel.add(_excuseButton, DockPanel.SOUTH);

		Const.eWywiadowkaService.getAbsences(student,
				new AsyncCallback<LinkedList<AbsenceDTO>>() {

					@Override
					public void onFailure(Throwable caught) {
						Window.alert(caught.getMessage());
					}

					@Override
					public void onSuccess(LinkedList<AbsenceDTO> result) {
						_absences = result;

						_headerTable = new FixedWidthFlexTable();
						_headerTable.setBorderWidth(1);
						fillHeader();

						_dataTable = new FixedWidthGrid(_absences.size(), 3);
						_dataTable.setBorderWidth(1);
						repaintTable();

						_dockPanel.remove(_scrollTable);

						_scrollTable = new ScrollTable(_dataTable, _headerTable);
						_scrollTable.setHeight("400px");
						_scrollTable.setVisible(true);

						_dataTable.addTableListener(_me);
						_scrollTable.setSortPolicy(SortPolicy.DISABLED);

						_dockPanel.add(_scrollTable, DockPanel.CENTER);
						_scrollTable.fillWidth();
					}

				});
		_mainPanel.add(_dockPanel);
		this.initWidget(_mainPanel);

	}

	private void repaintTable() {
		int i = 0;
		for (AbsenceDTO student : _absences)
			fillRow(i++, student);
	}

	private void fillRow(int row, AbsenceDTO absence) {

		RowFormatter rowFormatter = _dataTable.getRowFormatter();

		if (row % 2 == 0)
			rowFormatter.addStyleName(row, "tableRowStyle1");
		else
			rowFormatter.addStyleName(row, "tableRowStyle2");

		_dataTable.setHTML(row, 0, absence.start.toString());
		_dataTable.setHTML(row, 1, absence.stop.toString());
		_dataTable.setHTML(row, 2, absence.excused.toString());
	}

	private void fillHeader() {
		_headerTable.setHTML(0, 0, "Poczatek");
		_headerTable.setHTML(0, 1, "Koniec");
		_headerTable.setHTML(0, 2, "Usprawiedliwienie");
	}

	@Override
	public void onCellClicked(SourcesTableEvents sender, int row, int cell) {
		RowFormatter rowFormatter = _dataTable.getRowFormatter();
		if (_selectedRow != -1) {
			if (_selectedRow % 2 == 0)
				rowFormatter.setStyleName(_selectedRow, "tableRowStyle1");
			else
				rowFormatter.setStyleName(_selectedRow, "tableRowStyle2");
		}
		_selectedRow = row;
		rowFormatter.setStyleName(row, "clickedTableRowStyle");

		if (_absences.get(row).excused)
			_excuseButton.setText("Cofnij usprawiedliwienie");
		else
			_excuseButton.setText("Usprawiedliw nieobecnosc");
	}

	private void fillAbsences(LinkedList<AbsenceDTO> absences) {
		_absences = absences;

		_headerTable = new FixedWidthFlexTable();
		_headerTable.setBorderWidth(1);
		fillHeader();

		_dataTable = new FixedWidthGrid(_absences.size(), 3);
		_dataTable.setBorderWidth(1);
		repaintTable();

		_dockPanel.remove(_scrollTable);

		_scrollTable = new ScrollTable(_dataTable, _headerTable);
		_scrollTable.setHeight("400px");
		_scrollTable.setVisible(true);

		_dataTable.addTableListener(_me);
		_scrollTable.setSortPolicy(SortPolicy.DISABLED);

		_dockPanel.add(_scrollTable, DockPanel.CENTER);
		_scrollTable.fillWidth();

	}

	@Override
	public void onClick(ClickEvent event) {
		if (event.getSource() == _excuseButton) {
			if (_selectedRow != -1) {

				AbsenceDTO absence = _absences.get(_selectedRow);
				absence.excused = !absence.excused;

				Const.eWywiadowkaService.excuseAbsence(absence,
						new AsyncCallback<Boolean>() {

							@Override
							public void onFailure(Throwable caught) {
								Window.alert(caught.getMessage());
							}

							@Override
							public void onSuccess(Boolean result) {
								Window.alert(result ? "Operacja powiodla sie"
										: "Blad operacji");
								if (result)
									Const.eWywiadowkaService
											.getAbsences(
													_student,
													new AsyncCallback<LinkedList<AbsenceDTO>>() {

														@Override
														public void onFailure(
																Throwable caught) {
															Window
																	.alert(caught
																			.getMessage());
														}

														@Override
														public void onSuccess(
																LinkedList<AbsenceDTO> result) {
															fillAbsences(result);
														}

													});
							}

						});

			} else
				Window.alert("Prosze wybrac nieobecnosc");

		} else if (event.getSource() == _addButton) {
			if (_startDateBox.getValue() != null
					&& _stopDateBox.getValue() != null) {

				AbsenceDTO absence = new AbsenceDTO(_student, null,
						_startDateBox.getValue(), _stopDateBox.getValue(),
						_excusedCheckBox.getValue());

				Const.eWywiadowkaService.addAbsence(absence,
						new AsyncCallback<AbsenceRegisterMsg>() {

							@Override
							public void onFailure(Throwable caught) {
								Window.alert(caught.getMessage());
							}

							@Override
							public void onSuccess(AbsenceRegisterMsg result) {
								Window.alert(result.toString());
								if (result == AbsenceRegisterMsg.OK)
									Const.eWywiadowkaService
											.getAbsences(
													_student,
													new AsyncCallback<LinkedList<AbsenceDTO>>() {

														@Override
														public void onFailure(
																Throwable caught) {
															Window
																	.alert(caught
																			.getMessage());
														}

														@Override
														public void onSuccess(
																LinkedList<AbsenceDTO> result) {
															fillAbsences(result);
														}

													});

							}

						});
			} else
				Window.alert("Prosze wypelnic daty nieobecnosci");
		} else if (event.getSource() == _removeButton) {

			if (_selectedRow != -1) {
				
				AbsenceDTO absence = _absences.get(_selectedRow);
				
				Const.eWywiadowkaService.removeAbsence(absence,
						new AsyncCallback<Boolean>() {

							@Override
							public void onFailure(Throwable caught) {
								Window.alert(caught.getMessage());
							}

							@Override
							public void onSuccess(Boolean result) {
								Window.alert(result ? "Usunieto nieobecnosc"
										: "Blad usuwania");
								if (result)
									Const.eWywiadowkaService
											.getAbsences(
													_student,
													new AsyncCallback<LinkedList<AbsenceDTO>>() {

														@Override
														public void onFailure(
																Throwable caught) {
															Window
																	.alert(caught
																			.getMessage());
														}

														@Override
														public void onSuccess(
																LinkedList<AbsenceDTO> result) {
															fillAbsences(result);
														}

													});
							}

						});
				} else
					Window.alert("Prosze wybrac nieobecnosc");
		}
	}
}
